;***********************************************************************
; ACDM_sub.asm
;
; provides subroutines for the display manager
;
;***********************************************************************

section .text

global ClearBuff
global ClearChars
global ClearBuffLine
global ClearCharsLine

global BuffCopy
global RibbonCopy

global ACDMSpinEnter
global ACDMSpinLeave

global DisableBlink

;***********************************************************************
; routine to disable the VGA blink

DisableBlink:
	; Disable blink
	mov		dx, 0x3DA
	in		al, dx
	mov		dx, 0x3C0
	mov		al, 0x30
	out		dx, al
	inc		dx
	in		al, dx
	and		al, 0xF7
	dec		dx
	out		dx, al

	; finished
	ret

;***********************************************************************
; function to copy an entire static buffer to another
BuffCopy:
	; need to copy 3680 bytes from address from rdi to rsi
	; save registers
	push	rbx
	push	r12
	push	r13
	push	r14

	; setup for main loop
	mov		rcx, 46			; 46 x 8 bytes per register x 10 registers

.loop:
	; main loop
	; read from source
	mov		rax, [rdi]
	mov		rbx, [rdi + 8]
	mov		rdx, [rdi + 16]
	mov		r8, [rdi + 24]
	mov		r9, [rdi + 32]
	mov		r10, [rdi + 40]
	mov		r11, [rdi + 48]
	mov		r12, [rdi + 56]
	mov		r13, [rdi + 64]
	mov		r14, [rdi + 72]

	; write to destination
	mov		[rsi], rax
	mov		[rsi + 8], rbx
	mov		[rsi + 16], rdx
	mov		[rsi + 24], r8
	mov		[rsi + 32], r9
	mov		[rsi + 40], r10
	mov		[rsi + 48], r11
	mov		[rsi + 56], r12
	mov		[rsi + 64], r13
	mov		[rsi + 72], r14

	add		rdi, 80			; add 80 bytes to source address
	add		rsi, 80			; add 80 bytes to destination address
	loop	.loop			; aand repeat

	; save rsi and rdi
	;push 	rsi
	;push 	rdi

	; setup for loop to copy chars
	;mov 	rcx, 3680/2

;.loop:
	;mov 	bl, [rdi]
	;mov 	[rsi], bl
	;add		rdi, 2
	;add		rsi, 2
	;loop	.loop

	; restore rsi and rdi
	;pop 	rdi
	;pop 	rsi

	; setup for loop to copy attributes
	;mov 	rcx, 3680/2

;.loop2:
	;mov 	bl, [rdi + 1]
	;mov 	[rsi + 1], bl
	;add 	rdi, 2
	;add 	rsi, 2
	;loop 	.loop2

	; finished
	pop		r14
	pop		r13
	pop		r12
	pop		rbx
	ret

;***********************************************************************
; function to copy a ribbon to another
RibbonCopy:
	; need to copy 160 bytes from address in rdi to rsi
	; save registers
	push	rbx
	push	r12
	push	r13
	push	r14

	; setup for main loop
	mov		rcx, 2			; 2 x 8 bytes per register x 10 registers

.loop:
	; main loop
	; read from source
	; read from source
	mov		rax, [rdi]
	mov		rbx, [rdi + 8]
	mov		rdx, [rdi + 16]
	mov		r8, [rdi + 24]
	mov		r9, [rdi + 32]
	mov		r10, [rdi + 40]
	mov		r11, [rdi + 48]
	mov		r12, [rdi + 56]
	mov		r13, [rdi + 64]
	mov		r14, [rdi + 72]

	; write to destination
	mov		[rsi], rax
	mov		[rsi + 8], rbx
	mov		[rsi + 16], rdx
	mov		[rsi + 24], r8
	mov		[rsi + 32], r9
	mov		[rsi + 40], r10
	mov		[rsi + 48], r11
	mov		[rsi + 56], r12
	mov		[rsi + 64], r13
	mov		[rsi + 72], r14

	add		rdi, 80			; add 80 bytes to source address
	add		rsi, 80			; add 80 bytes to destination address
	loop	.loop			; aand repeat

	; finished
	pop		r14
	pop		r13
	pop		r12
	pop		rbx
	ret

;***********************************************************************
; function to clear an entire buffer pointed to by rdi
ClearBuff:
	; setup for the loop
	mov		rcx, 46
	xor		rax, rax

.loop:
	mov		[rdi], rax
	mov		[rdi + 8], rax
	mov		[rdi + 16], rax
	mov		[rdi + 24], rax
	mov		[rdi + 32], rax
	mov		[rdi + 40], rax
	mov		[rdi + 48], rax
	mov		[rdi + 56], rax
	mov		[rdi + 64], rax
	mov		[rdi + 72], rax
	add		rdi, 80
	loop	.loop

	; finished
	ret

;***********************************************************************
; function to clear all chars in a buffer pointed to by rdi
ClearChars:
	; setup for the loop
	mov		rcx, 184
	xor		rax, rax

.loop:
	mov		[rdi], al
	mov		[rdi + 2], al
	mov		[rdi + 4], al
	mov		[rdi + 6], al
	mov		[rdi + 8], al
	mov		[rdi + 10], al
	mov		[rdi + 12], al
	mov		[rdi + 14], al
	mov		[rdi + 16], al
	mov		[rdi + 18], al
	add		rdi, 20
	loop	.loop

	; finished
	ret

;***********************************************************************
; function to clear a buffer line pointed to by rdi
ClearBuffLine:
	; setup for the loop
	mov		rcx, 2
	xor		rax, rax

.loop:
	mov		[rdi], rax
	mov		[rdi + 8], rax
	mov		[rdi + 16], rax
	mov		[rdi + 24], rax
	mov		[rdi + 32], rax
	mov		[rdi + 40], rax
	mov		[rdi + 48], rax
	mov		[rdi + 56], rax
	mov		[rdi + 64], rax
	mov		[rdi + 72], rax
	add		rdi, 80
	loop	.loop

	; finished
	ret

;***********************************************************************
; function to clear all chars in a line pointed to by rdi
ClearCharsLine:
	; setup for the loop
	mov		rcx, 8
	xor		rax, rax

.loop:
	mov		[rdi], al
	mov		[rdi + 2], al
	mov		[rdi + 4], al
	mov		[rdi + 6], al
	mov		[rdi + 8], al
	mov		[rdi + 10], al
	mov		[rdi + 12], al
	mov		[rdi + 14], al
	mov		[rdi + 16], al
	mov		[rdi + 18], al
	add		rdi, 20
	loop	.loop

	; finished
	ret

;***********************************************************************
; spinlock entry
; rdi = ptr to lock byte

ACDMSpinEnter:
	; attempt to acquire the lock
	mov			eax, 0
	lock bts	[rdi], eax
	jnc			.acquired

.retest:
	; check if the lock is free before trying again
	pause
	test		BYTE [rdi], 1
	jnz			.retest

	; lock is open, attempt to acquire it
	mov			eax, 0
	lock bts	[rdi], eax
	jc			.retest

.acquired:
	; lock is acquired, continue into critical region
	ret


;***********************************************************************
; spinlock exit
; rdi = ptr to lock byte

ACDMSpinLeave:
	; release lock
	mov			[rdi], BYTE 0
	ret
